package com.torbinsky.esw;

import java.io.File;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Logger;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.impl.DefaultFileMonitor;

import com.torbinsky.esw.impl.WatchedDirectoryListener;

/**
 * @author Torben Werner
 * 
 * Description: Watches a directory (watchPath) for incoming files. If a new file is added to the watched
 * directory, it is scanned to check if it matches any patterns and outputs any such matches to a file.
 * 
 * Usage: EmailSpamWatcher -DwatchPath=/foo/bar/watch_dir -DhostOut=/foo/bar/host.out -DrecvBy=mail.foo.com -DipOut=/foo/bar/ip.out
 *
 */
public class EmailSpamWatcher {
	private static final Logger log = Logger.getLogger(EmailSpamWatcher.class.getName());
	/*
	 * Constants
	 */
	public static final long FILE_POLLING_INTERVAL_MS = 1000; // every 1 second
	
	/*
	 * Arguments
	 */
	public static final String MONITORED_DIRECTORY_ARG = "watchPath";
	public static final String HOSTNAME_OUTPUT_FILE_PATH_ARG = "hostOut";
	public static final String IP_ADDRESS_OUTPUT_FILE_PATH_ARG = "ipOut";
	private static final String RECEIVED_BY_SERVER_ARG = "recvBy";
	
	/*
	 * MAIN
	 */
	public static void main(String[] args) throws IOException, InterruptedException {
		// Initialize default watch directory and output file paths - provides defaults in case the values aren't found in our system properties
		Properties properties = System.getProperties();
		String receiveByServer = properties.getProperty(RECEIVED_BY_SERVER_ARG, "localhost");
		String currentDirectory = new File (".").getCanonicalPath();
		String watchPath = properties.getProperty(MONITORED_DIRECTORY_ARG, currentDirectory);
		String hostOutPath = properties.getProperty(HOSTNAME_OUTPUT_FILE_PATH_ARG, currentDirectory + "/host.out");
		String ipOutPath = properties.getProperty(IP_ADDRESS_OUTPUT_FILE_PATH_ARG, currentDirectory + "/ip.out");
		
		FileObject watchDir = null;
		FileObject hostFile = null;
		FileObject ipFile = null;
		try{
			// Get a handle to the FileSystemManager so we can initialize our FileObject's
			FileSystemManager manager = VFS.getManager();
			
			// Open the watch directory path and make sure it is actually a directory
			watchDir = manager.resolveFile(watchPath);
			if(watchDir.getType() != FileType.FOLDER){
				// Bail out, we only want directories
				throw new IllegalArgumentException("Watch path is not a valid directory!");
			}
			
			// Open the output files (will error out with exceptions if any of the files aren't valid)
			hostFile = manager.resolveFile(hostOutPath);
			hostFile.createFile();
			ipFile = manager.resolveFile(ipOutPath);
			ipFile.createFile();
			
			// Set up our file monitor which will detect any new files being added to the watched directory
			log.info("Monitoring " + watchPath + " for new files. Outputting host matches to " + hostOutPath + " and ip matches to " + ipOutPath);
			DefaultFileMonitor fm = new DefaultFileMonitor(new WatchedDirectoryListener(hostFile, ipFile, receiveByServer));
			fm.setDelay(FILE_POLLING_INTERVAL_MS);
			fm.addFile(watchDir); // Add our watch directory
			fm.start(); // start watching
			do{
				Thread.sleep(1000);
			}while(true);
		} catch(FileSystemException e){
			log.severe("Encountered exception starting up monitoring service.");
			e.printStackTrace();
		} finally {
			log.info("Exiting spam watcher...");
			// Cleanup any open files we might have before exiting
			if(watchDir != null){
				watchDir.close();
			}
			if(hostFile != null){
				hostFile.close();
			}
			if(ipFile != null){
				ipFile.close();
			}
		}
	}
}
